package com.zhanghu.hibernate.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zhanghu.hibernate.dto.SampleDTO;
import com.zhanghu.hibernate.dto.UserDTO;
import com.zhanghu.hibernate.dto.UserVO;
import com.zhanghu.hibernate.entity.Names;
import com.zhanghu.hibernate.entity.NamesOnly;
import com.zhanghu.hibernate.entity.NamesUser;
import com.zhanghu.hibernate.entity.ZkUser;
import com.zhanghu.hibernate.repository.UserPageAndSortRepository;
import com.zhanghu.hibernate.repository.ZkUserRepository;
import com.zhanghu.hibernate.service.ZkUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @Author: zhanghu
 * @Description:
 * @Date: Create in 9:37 2020/1/7
 * @modified by:
 */
@RestController
public class ZkUserController {
    @Autowired
    private ZkUserService zkUserService;
    @Autowired
    private ZkUserRepository zkUserRepository;
    @Autowired
    private UserPageAndSortRepository userPageAndSortRepository;
    //    @Autowired
//    private TestRepository testRepository;
    @Autowired
    @PersistenceContext
    private EntityManager entityManager;
    @GetMapping("/users")
    public List<ZkUser> findAll() {
        return zkUserService.findAll();
    }


    @PostMapping("/user")
    public ZkUser save(ZkUser zkUser) {
        return zkUserService.save(zkUser);
    }


    @GetMapping("/page/users")
    public Page<ZkUser> findAllPage(Integer page, Integer limit) {
        Sort sort = Sort.by(Sort.Direction.DESC, "username");
        return userPageAndSortRepository.findAll(PageRequest.of(page, limit, sort));
    }
    @GetMapping("/sort/users")
    public Iterable<ZkUser> findAllSort() {
        Sort sort = Sort.by(Sort.Direction.DESC, "username");
        return userPageAndSortRepository.findAll(sort);
    }

    @GetMapping("/name")
    public Collection<Names> selectByName(String name) {

        return zkUserRepository.findByName(name);
    }
    @GetMapping("/names")
    public List<NamesOnly> selectAll() {

        return zkUserRepository.findAlls();
    }
    @GetMapping("/names1")
    public List<NamesUser> selectAll1() {

        return zkUserRepository.findAllss();
    }

    @GetMapping("/users/all")
    public List<UserDTO> selectAl() {

        return zkUserRepository.findAlss();
    }
    @GetMapping("/users/alls")
    public List<UserVO> selectAls() {

        return zkUserRepository.findAlNative();
    }

    @GetMapping("/all")
    public List<ZkUser> selectsAls(ZkUser user) {

        return zkUserRepository.get(user);
    }

    @GetMapping("/t")
    public Object s(String name) {
        List<Map<String, Object>> map = zkUserRepository.findDtos(name);
        List<SampleDTO> sampleDTOS = JSON.parseArray(JSONObject.toJSONString(map), SampleDTO.class);
        return sampleDTOS;
    }
    @GetMapping("/aa")
    public String aa() {
        return "aa";
    }
    @GetMapping("/bb")
    public String bb() {
        return "bb";
    }
    @GetMapping("/allb")
    public List<ZkUser> getAll(ZkUser user) {
        return zkUserRepository.findAll(new Specification<ZkUser>() {
            @Override
            public Predicate toPredicate(Root<ZkUser> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> specifications = new ArrayList<>();
                if (StringUtils.isNotBlank(user.getUsername())) {
                    specifications.add(criteriaBuilder.like(root.get("username"),"%"+user.getUsername()+"%" ));
                }
                if (StringUtils.isNotBlank(user.getName())) {
                    specifications.add(criteriaBuilder.like(root.get("name"),"%"+user.getName()+"%" ));
                }

                if (null != user.getId()) {
                    specifications.add(criteriaBuilder.equal(root.get("id"), user.getId()));
//
                }
                specifications.add(criteriaBuilder.equal(root.join("zUser", JoinType.INNER).get("id"),root.get("id")));
                return query.where(specifications.toArray(new Predicate[specifications.size()])).getRestriction();
            }
        });

    }

    @GetMapping("/alla")
    public Object selectsAlsa(ZkUser user) {

        ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("name", ExampleMatcher.GenericPropertyMatchers.exact())
                .withMatcher("username", ExampleMatcher.GenericPropertyMatchers.startsWith())
                .withIgnorePaths("id");
        Example example = Example.of(user, exampleMatcher);
        return zkUserRepository.findAll(example);
    }


    @GetMapping("/test")
    public List<ZkUser> getAll() {

        System.out.println(entityManager.find(ZkUser.class, 1));
        Query query = entityManager.createQuery("select u from ZkUser u");

        return query.getResultList();
    }


    @GetMapping("/tes")
    public List<UserDTO> test(ZkUser zkUser) {
        StringBuilder sql = new StringBuilder("select new com.zhanghu.hibernate.dto.UserDTO(u.name, u.username) from ZkUser u inner join ZUser z on u.id=z.id where 1=1");
        if (zkUser.getId() != null) {
            sql.append(" and u.id=?1");
        }
        if (StringUtils.isNotBlank(zkUser.getName())) {
            sql.append(" and u.name = ?2");
        }
        TypedQuery<UserDTO> query = entityManager.createQuery(sql.toString(),  UserDTO.class);
        if (zkUser.getId() != null) {
            query.setParameter(1, zkUser.getId());
        }
        if (StringUtils.isNotBlank(zkUser.getName())) {
            query.setParameter(2, zkUser.getName());
        }
        List<UserDTO> result = query.getResultList();
        return result;
    }
}

